#pragma once

#include <cstddef>
#include <cstring>
#include <cassert>

namespace p2pms 
{

class String 
{
public:
    String() : data(nullptr), size(0) {}
    String(const char* s, size_t len) 
    {
        size = len;
        data = (char*)malloc(size + 1);
        memcpy(data, s, size);
        data[size] = '\0';
    }
    
    String(const char* s) : String(s, strlen(s)) {}
    String(const std::string& s) : String(s.data(), s.size()) {}
    String(const String& other) : String(other.data, other.size) {}
    String& operator=(const String& other) 
    {
        if (this != &other) {
            free(data);
            size = other.size;
            data = (char*)malloc(size + 1);
            memcpy(data, other.data, size);
            data[size] = '\0';
        }
        return *this;
    }
    ~String() { free(data); }

    void clear() { free(data); data = nullptr; size = 0; }

    bool empty() const { return size == 0; }

    char& operator[](size_t i) { assert(i < size); return data[i]; }

    const char& operator[](size_t i) const { assert(i < size); return data[i]; }

    const char* c_str() const { return data ? data : ""; }

    std::string to_std_string() const { return std::string(data, size); }

private:
    char* data;
    size_t size;
};

} // namespace p2pms